﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace QuickRunCore.Helper
{
    public class WinAPI
    {
        //函数指针类型
        public delegate bool EnumWindowsProc(int hWnd, int lParam);

        [DllImport("user32.dll")]

        //EnumWindows函数，EnumWindowsProc 为处理函数
        public static extern int EnumWindows(EnumWindowsProc ewp, int lParam);

        #region EnumDesktopWindows 

        public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, uint lParam);

        [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", ExactSpelling = false,

        CharSet = CharSet.Auto, SetLastError = true)]

        [return: MarshalAs(UnmanagedType.Bool)]

        public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsDelegate lpEnumCallbackFunction, IntPtr lParam);

        #endregion

        /// <summary>
        /// 获得指定窗口的可视状态，即显示或者隐藏
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool IsWindowVisible(int hWnd);

        /// <summary>
        /// 指定窗口的标题条文本（如果存在）拷贝到一个缓存区内
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="lpString"></param>
        /// <param name="nMaxCount"></param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);

        [DllImport("user32.dll")]
        public static extern int GetWindowTextLength(int hWnd);

        /// <summary>
        /// IsIconic
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsIconic(IntPtr hWnd);
        /// <summary>
        /// 确定窗口是否是最大化的窗口
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool IsZoomed(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);   //获取线程ID 

        public const int PROCESS_ALL_ACCESS = 0x000F0000 | 0x00100000 | 0xFFF;

        [DllImport("Kernel32.dll")]
        public extern static IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("Kernel32.dll", EntryPoint = "QueryFullProcessImageNameW", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        public extern static int QueryFullProcessImageName(IntPtr hProcess, UInt32 flags, char[] exeName, ref UInt32 nameLen);


        public const int SW_HIDE = 0;
        public const int SW_NORMAL = 1;    //正常弹出窗体 
        public const int SW_MAXIMIZE = 3;    //最大化弹出窗体 
        public const int SW_SHOWNOACTIVATE = 4;
        public const int SW_SHOW = 5;
        public const int SW_MINIMIZE = 6;
        public const int SW_RESTORE = 9;
        public const int SW_SHOWDEFAULT = 10;

        [DllImport("User32.dll")]
        //返回值：如果窗口原来可见，返回值为非零；如果函数原来被隐藏，返回值为零。
        public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
    }

    public class WindowInfo
    {
        private IntPtr handle;
        /// <summary>
        /// 句柄
        /// </summary>
        public IntPtr Handle { get { return handle; } set { handle = value; } }

        private string title;
        /// <summary>
        /// 标题
        /// </summary>
        public string Title { get { return title; } set { title = value; } }

        private string processName;
        /// <summary>
        /// 进程名
        /// </summary>
        public string ProcessName { get { return processName; } set { processName = value; } }

        private string processPath;
        /// <summary>
        /// 进程路径
        /// </summary>
        public string ProcessPath { get { return processPath; } set { processPath = value; } }

        private bool isShow;
        /// <summary>
        /// 是否显示
        /// </summary>
        public bool IsShow { get { return isShow; } set { isShow = value; } }
    }




    public class HideWindow
    {
        static List<WindowInfo> _WindowInfoList = null;

        static List<WindowInfo> _CacheWindowInfoList = null;

        static List<Process> _ProcessList = null;

        public static List<WindowInfo> GetAllWindowInfoList(bool isShow)
        {
            _WindowInfoList = new List<WindowInfo>();

            _ProcessList = new List<Process>(Process.GetProcesses());

            WinAPI.EnumWindowsProc ewp = new WinAPI.EnumWindowsProc(ADA_EnumWindowsProc);
            WinAPI.EnumWindows(ewp, 0);

            _CacheWindowInfoList = _WindowInfoList.FindAll(m => m.IsShow == isShow);
            return _CacheWindowInfoList;
        }

        private static bool ADA_EnumWindowsProc(int hWnd, int lParam)
        {
            if (_CacheWindowInfoList != null && _CacheWindowInfoList.Find(m => m.Handle == new IntPtr(hWnd)) != null)
            {
                WindowInfo _wi = _CacheWindowInfoList.Find(m => m.Handle == new IntPtr(hWnd));
                _wi.IsShow = WinAPI.IsWindowVisible(hWnd);
                _WindowInfoList.Add(_wi);
            }
            else
            {

                int calcID = 0;    //线程ID
                WinAPI.GetWindowThreadProcessId(new IntPtr(hWnd), out calcID);
                Process myProcess = _ProcessList == null ? null : _ProcessList.Find(m => m.Id == calcID);
                string _processName = myProcess == null ? "" : myProcess.ProcessName;
                bool _isShow = WinAPI.IsWindowVisible(hWnd);

                

                WindowInfo _wi = _WindowInfoList.Find(m => (int)m.Handle == (int)myProcess.MainWindowHandle && m.IsShow == _isShow);
                if (_wi == null)
                {

                    #region 窗体标题文字

                    int _textLen;
                    String _titleText = "";
                    _textLen = WinAPI.GetWindowTextLength((int)myProcess.MainWindowHandle) + 1;
                    StringBuilder _sb = new StringBuilder(_textLen);
                    WinAPI.GetWindowText((int)myProcess.MainWindowHandle, _sb, _textLen);
                    _titleText = _sb.ToString();

                    #endregion

                    #region 窗体程序路径

                    string _processPath = "";

                    ////通过进程ID获取进程句柄
                    //IntPtr processHandle = IntPtr.Zero;
                    //const int PROCESS_ALL_ACCESS = 0x1F0FFF;
                    //const int PROCESS_VM_READ = 0x0010;
                    //const int PROCESS_VM_WRITE = 0x0020;
                    //processHandle = WinAPI.OpenProcess(PROCESS_ALL_ACCESS, false, calcID);

                    ////通过进程句柄获取进程主程序路径
                    //if (processHandle != IntPtr.Zero)
                    //{
                    //    try
                    //    {
                    //        char[] buf = new char[65535];
                    //        UInt32 len = 65535;
                    //        WinAPI.QueryFullProcessImageName(processHandle, 0, buf, ref len);
                    //        _processPath = new string(buf, 0, (int)len);


                    //    }
                    //    finally
                    //    {
                    //    }
                    //}

                    #endregion

                    if (_processName.ToLower() != "explorer" && _processName.ToLower() != "systemsettings" && _processName.ToLower() != "applicationframehost")
                    {
                        try
                        {
                            _WindowInfoList.Add(new WindowInfo
                            {
                                Handle = myProcess.MainWindowHandle,
                                Title = _titleText,
                                ProcessName = _processName,
                                ProcessPath = _processPath,
                                IsShow = _isShow
                            });
                        }
                        catch
                        {

                        }

                    }

                }

            }
            return true;
        }

        public static bool HideWindowFromHandle(IntPtr handle, bool isHide)
        {
            if (isHide)
            {
                WinAPI.ShowWindowAsync(handle, WinAPI.SW_HIDE);
            }
            else
            {
                WinAPI.ShowWindowAsync(handle, WinAPI.SW_SHOW);

            }


            return true;
        }
    }
}
